import 'dart:convert';
import 'dart:async';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:shared_preferences/shared_preferences.dart';

// import 'package:hm_pda_app/config/password_encryptor.dart';

class HttpUtil {
  static String baseUrl = dotenv.env['APP_BASE_API']!;
  // static String? token =
  //     'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJrMmxIQ1NMYjRkbkE3WUpjeGg2S3hHQlVWcE1sTldpNSIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwiZGVwdElkIjoxMDB9.jPQm5_TKXIH7nM42VFVIEOi8WwCwUeMlJFrojlw01v4';
  static String? token;
  static Map<String, dynamic> defaultHeaders = {
    'Content-Type': 'application/json; charset=utf-8',

    'Authorization': 'Bearer $token',
    'Clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e',
  };

  static http.Client? _client;
  static Duration timeout = Duration(seconds: 300);

  // 网络状态检查
  static final Connectivity _connectivity = Connectivity();

  // 初始化方法
  static Future<void> initialize({
    String? baseUrl,
    Map<String, dynamic>? headers,
    String? token,
    Duration? timeout,
  }) async {
    if (baseUrl != null) HttpUtil.baseUrl = baseUrl;
    if (headers != null) defaultHeaders.addAll(headers);
    if (token != null) {
      HttpUtil.token = token;
    } else {
      final prefs = await SharedPreferences.getInstance();
      HttpUtil.token = prefs.getString('token');
    }
    if (timeout != null) HttpUtil.timeout = timeout;

    // 初始化 HTTP 客户端
    _client ??= http.Client();

    print('HTTP Util 初始化完成');
    print('Base URL: $baseUrl');
    print('Timeout: $timeout');
  }

  static http.Client get _httpClient {
    if (_client == null) {
      throw Exception('HTTP Util 未初始化，请先调用 initialize() 方法');
    }
    return _client!;
  }

  // 检查网络连接
  static Future<bool> checkConnectivity() async {
    try {
      final connectivityResult = await _connectivity.checkConnectivity();
      return connectivityResult != ConnectivityResult.none;
    } catch (e) {
      print('网络连接检查失败: $e');
      return false;
    }
  }

  // 关闭 HTTP 客户端
  static void close() {
    _client?.close();
    _client = null;
    print('HTTP 客户端已关闭');
  }

  // 获取完整 URL
  static String _getFullUrl(String endpoint) {
    if (endpoint.startsWith('http')) {
      return endpoint;
    }

    String formattedBaseUrl = baseUrl.endsWith('/')
        ? baseUrl.substring(0, baseUrl.length - 1)
        : baseUrl;
    String formattedEndpoint = endpoint.startsWith('/')
        ? endpoint
        : '/$endpoint';

    return '$formattedBaseUrl$formattedEndpoint';
  }

  // 获取请求头
  static Map<String, dynamic> _getHeaders([
    Map<String, dynamic>? extraHeaders,
  ]) {
    Map<String, dynamic> headers = Map.from(defaultHeaders);

    if (token != null) {
      headers['Authorization'] = 'Bearer $token';
    }

    if (extraHeaders != null) {
      headers.addAll(extraHeaders);
    }

    return headers;
  }

  // 带超时和重试的请求封装
  static Future<http.Response> _makeRequestWithTimeout(
    Future<http.Response> Function() request, {
    int maxRetries = 2,
  }) async {
    // 检查网络连接
    if (!await checkConnectivity()) {
      throw HttpException(
        code: -1,
        message: '网络连接不可用，请检查网络设置',
        type: ErrorType.network,
      );
    }

    for (int attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        final response = await request().timeout(timeout);
        print('响应状态码: ${response.statusCode}');
        return response;
      } catch (e) {
        if (e is TimeoutException) {
          print('请求超时，重试 ${attempt + 1}/$maxRetries');
          if (attempt == maxRetries) {
            throw HttpException(
              code: -1,
              message: '请求超时，请检查网络连接',
              type: ErrorType.timeout,
            );
          }
          await Future.delayed(Duration(seconds: 1 * (attempt + 1)));
        } else {
          rethrow;
        }
      }
    }

    throw HttpException(code: -1, message: '请求失败', type: ErrorType.unknown);
  }

  // GET 请求
  static Future<HttpResponse> get(
    String endpoint, {
    Map<String, dynamic>? headers,
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      String url = _getFullUrl(endpoint);

      if (queryParameters != null && queryParameters.isNotEmpty) {
        final uri = Uri.parse(
          url,
        ).replace(queryParameters: _encodeQueryParameters(queryParameters));
        url = uri.toString();
      }

      print('📡 GET 请求: $url');

      final response = await _makeRequestWithTimeout(
        () => _httpClient.get(
          Uri.parse(url),
          headers: _getHeaders(
            headers,
          ).map((key, value) => MapEntry(key, value.toString())),
        ),
      );

      return _handleResponse(response);
    } catch (e) {
      print('❌ GET 错误: $e');
      return _handleError(e);
    }
  }

  // POST 请求
  static Future<HttpResponse> post(
    String endpoint, {
    dynamic data,
    Map<String, dynamic>? headers,
  }) async {
    try {
      final url = _getFullUrl(endpoint);
      print('📡 POST 请求: $url');
      print('📦 POST 数据: $data');
      print('📦 POST 请求头: $headers');

      final response = await _makeRequestWithTimeout(
        () => _httpClient.post(
          Uri.parse(url),
          headers: _getHeaders(
            headers,
          ).map((key, value) => MapEntry(key, value.toString())),
          body: data is Map || data is List ? jsonEncode(data) : data,
        ),
      );
      print('📦 POST 响应: ${response.body}');
      return _handleResponse(response);
    } catch (e) {
      print('❌ POST 错误: $e');
      if (e is FormatException) {
        print('❌ 数据格式错误，可能是加密数据解析失败: ${e.message}');
        return HttpResponse(
          success: false,
          code: -2,
          data: null,
          message: '数据格式错误，可能是加密数据解析失败: ${e.message}',
          rawResponse: null,
          isJson: false,
          errorType: ErrorType.client,
        );
      }
      return _handleError(e);
    }
  }

  // 文件上传 - 使用 File 对象
  static Future<HttpResponse> uploadFile(
    String endpoint, {
    required File file,
    String? fileName,
    Map<String, dynamic>? headers,
    Map<String, dynamic>? fields,
  }) async {
    try {
      final bytes = await file.readAsBytes();
      final name = fileName ?? file.path.split('/').last;

      return await upload(
        endpoint,
        bytes,
        headers: headers,
        fileName: name,
        fields: fields,
      );
    } catch (e) {
      print('❌ 文件读取错误: $e');
      return _handleError(e);
    }
  }

  // 文件上传
  static Future<HttpResponse> upload(
    String endpoint,
    List<int> fileBytes, {
    Map<String, dynamic>? headers,
    String? fileName,
    Map<String, dynamic>? fields,
  }) async {
    try {
      final url = _getFullUrl(endpoint);

      var request = http.MultipartRequest('POST', Uri.parse(url));

      // 添加文件
      request.files.add(
        http.MultipartFile.fromBytes('file', fileBytes, filename: fileName),
      );

      // 添加其他字段
      if (fields != null) {
        request.fields.addAll(
          fields.map((key, value) => MapEntry(key, value.toString())),
        );
      }

      // 添加 headers
      final allHeaders = _getHeaders(headers);
      allHeaders.remove('Content-Type'); // Multipart 请求会自动设置
      request.headers.addAll(
        allHeaders.map((key, value) => MapEntry(key, value.toString())),
      );

      print('📡 文件上传: $url');
      print('📁 文件名: $fileName');

      final response = await _makeRequestWithTimeout(() async {
        final streamedResponse = await request.send();
        return await http.Response.fromStream(streamedResponse);
      });
      return _handleResponse(response);
    } catch (e) {
      print('❌ 上传错误: $e');
      return _handleError(e);
    }
  }

  // 处理响应
  static HttpResponse _handleResponse(http.Response response) {
    final statusCode = response.statusCode;

    print('📨 响应状态: $statusCode');
    print('🔗 响应URL: ${response.request?.url}');

    dynamic data;
    String rawResponse;
    try {
      // 尝试解析为JSON来判断是否是JSON字符串
      jsonDecode(response.body);
      rawResponse = response.body;
    } catch (e) {
      // 如果不是JSON字符串，则转换为JSON字符串
      rawResponse = jsonEncode(response.body);
    }
    bool isJson = false;
    Map<String, dynamic>? responseMap;
    int responseCode = statusCode;
    String responseMessage = _getMessage(statusCode);
    bool success = statusCode >= 200 && statusCode < 300;
    print('列表数据---${response.body}');
    if (rawResponse.isNotEmpty) {
      try {
        responseMap = jsonDecode(response.body) as Map<String, dynamic>;
        data = responseMap['data'] ?? responseMap;
        isJson = true;

        // 安全地获取响应代码和消息
        responseCode = responseMap['code'] ?? statusCode;
        responseMessage =
            responseMap['msg'] ??
            responseMap['message'] ??
            _getMessage(responseCode);
        success = responseCode == 200;

        print('✅ JSON 解析成功');
        print('📋 响应数据: $responseMap');
      } catch (e) {
        data = rawResponse;
        print('⚠️ 非 JSON 响应，返回原始内容: $e');
      }
    } else {
      data = null;
    }

    return HttpResponse(
      success: success,
      code: responseCode,
      data: data,
      message: responseMessage,
      rawResponse: rawResponse,
      isJson: isJson,
    );
  }

  // 错误处理
  static HttpResponse _handleError(dynamic error) {
    if (error is HttpException) {
      return HttpResponse(
        success: false,
        code: error.code,
        data: null,
        message: error.message,
        rawResponse: null,
        isJson: false,
        errorType: error.type,
      );
    }

    return HttpResponse(
      success: false,
      code: -1,
      data: null,
      message: error.toString(),
      rawResponse: null,
      isJson: false,
      errorType: ErrorType.unknown,
    );
  }

  static Map<String, dynamic> _encodeQueryParameters(
    Map<String, dynamic> parameters,
  ) {
    return parameters.map((key, value) {
      return MapEntry(key, value.toString());
    });
  }

  static String _getMessage(int code) {
    switch (code) {
      case 200:
        return '请求成功';
      case 201:
        return '创建成功';
      case 400:
        return '请求参数错误';
      case 401:
        return '未授权，请重新登录';
      case 403:
        return '禁止访问';
      case 404:
        return '资源未找到';
      case 500:
        return '服务器错误';
      case 502:
        return '网关错误';
      case 503:
        return '服务不可用';
      default:
        return '网络请求失败 (状态码: $code)';
    }
  }

  // 更新 Token
  static void updateToken(String newToken) {
    token = newToken;
    print('🔑 Token 已更新');
  }

  // 清除 Token
  static void clearToken() {
    token = null;
    print('🔑 Token 已清除');
  }
}

// 自定义异常类
class HttpException implements Exception {
  final int code;
  final String message;
  final ErrorType type;

  HttpException({
    required this.code,
    required this.message,
    required this.type,
  });

  @override
  String toString() {
    return 'HttpException{code: $code, message: $message, type: $type}';
  }
}

enum ErrorType { network, timeout, server, client, unknown }

// 响应数据模型
class HttpResponse {
  final bool success;
  final int code;
  final dynamic data;
  final String message;
  final String? rawResponse;
  final bool isJson;
  final ErrorType? errorType;

  HttpResponse({
    required this.success,
    required this.code,
    required this.data,
    required this.message,
    this.rawResponse,
    this.isJson = true,
    this.errorType,
  });

  Map<String, dynamic>? get jsonData {
    if (isJson && data is Map) {
      return Map<String, dynamic>.from(data);
    }
    return null;
  }

  List<dynamic>? get listData {
    if (isJson && data is List) {
      return List<dynamic>.from(data);
    }
    return null;
  }

  @override
  String toString() {
    return 'HttpResponse{\n'
        '  success: $success,\n'
        '  code: $code,\n'
        '  message: $message,\n'
        '  errorType: $errorType,\n'
        '  isJson: $isJson,\n'
        '  data: ${data != null ? (data is Map || data is List ? jsonEncode(data) : data.toString()) : 'null'}\n'
        '}';
  }
}
